package chapter5_基础构建模块.同步工具类;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

/**
 * 使用栅栏，协调细胞自动衍生系统中的计算
 */
public class CellularAutomata {
    private final Board mainBoard;
    private final CyclicBarrier barrier;
    private final Worker[] workers;

    public CellularAutomata(Board mainBoard) {
        this.mainBoard = mainBoard;
        int count = Runtime.getRuntime().availableProcessors();
        // 分配一定数量(cpu数量)的线程
        this.barrier = new CyclicBarrier(count, new Runnable() {
            @Override
            public void run() {
                // 所有线程到达栅栏时，提交新值做更新
                mainBoard.commitNewValues();
            }
        });
        this.workers = new Worker[count];
    }

    private class Worker implements Runnable {
        private final Board board;

        public Worker(Board board) {
            this.board = board;
        }

        @Override
        public void run() {
            while (!board.hasConverged()) {
                for (int x = 0; x < board.getMaxX(); x++) {
                    for (int y = 0; y < board.getMaxY(); y++) {
                        // 先结果计算
                        board.setNewValue(x, y, computeValue(x, y));
                    }
                }

                try {
                    // 等待其他线程执行结束
                    barrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }
        }

        //构造的假方法
        private int computeValue(int x, int y) {
            return 10;
        }
    }

    public void start() {
        for (int i = 0; i < workers.length; i++) {
            new Thread(workers[i]).start();
        }
        mainBoard.waitForConvergence();
    }

}

class Board {
    //构造的一系列假方法
    public void commitNewValues() {
    }

    public boolean hasConverged() {
        return true;
    }

    public int getMaxX() {
        return 10;
    }

    public int getMaxY() {
        return 10;
    }

    public void setNewValue(int x,int y, int result) {
    }

    public void waitForConvergence() {
    }
}

class Worker {
}